package com.b511.swpu.cementbackend.util;

import com.b511.swpu.cementbackend.entity.*;
import com.b511.swpu.cementbackend.repository.MetaSystemUnitValueRepository;
import com.b511.swpu.cementbackend.repository.MetaTableRepository;
import com.b511.swpu.cementbackend.util.convert.Context;
import com.b511.swpu.cementbackend.util.convert.TypeFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class UnitUtil {

    private final MetaSystemUnitValueRepository metaSystemUnitValueRepository;

    private final MetaTableRepository metaTableRepository;

    public UnitUtil(MetaSystemUnitValueRepository metaSystemUnitValueRepository, MetaTableRepository metaTableRepository) {
        this.metaSystemUnitValueRepository = metaSystemUnitValueRepository;
        this.metaTableRepository = metaTableRepository;
    }

    public void transformUnit(List source, Class sourceClass, SysUser sysUser) {
        Map<String, Context> dict = mergeDict(sourceClass, sysUser);
        source.forEach(from -> {
            BeanWrapper wrapper = new BeanWrapperImpl(from);
            for (java.beans.PropertyDescriptor pd : wrapper.getPropertyDescriptors()) {
                String filedName = pd.getName();
                Object value = wrapper.getPropertyValue(filedName);
                if (null != value && dict.containsKey(filedName)) {
                    Context context = dict.get(filedName);
                    context.setValue((Double) value);
                    wrapper.setPropertyValue(filedName, context.getValue());
                }
            }
        });
    }

    // key字段名 value转换器
    private Map<String, Context> mergeDict(Class sourceClass, SysUser sysUser) {
        Map<String, String> tableFieldType = getTableFieldType(sourceClass);
        Map<String, Context> userPreference = getUserPreference(sysUser);
        Map<String, Context> result = new HashMap<>();
        for (Map.Entry<String, String> entry : tableFieldType.entrySet()) {
            if (userPreference.containsKey(entry.getValue())) {
                result.put(entry.getKey(), userPreference.get(entry.getValue()));
            }
        }
        return result;
    }

    //获取每个字段类型 字段 type
    private Map<String, String> getTableFieldType(Class table) {
        MetaTable metaTable = metaTableRepository.findByTableName(Help.humpToLine(table.getSimpleName()));
        Map<String, String> result = new HashMap<>();
        metaTable.getMetaFields().forEach(field -> {
            if (null != field.getMetaUnitCategory()) {
                result.put(Help.lineToHump(field.getFiledName()), field.getMetaUnitCategory().getUnitName());
            }
        });
        return result;
    }

    //获取用户使用习惯字典 type 转换器
    private Map<String, Context> getUserPreference(SysUser sysUser) {
        //获取用户使用习惯
        MetaSystemUnit metaSystemUnit = sysUser.getMetaSystemUnit();
        //用户类型使用习惯
        List<MetaSystemUnitValue> values = metaSystemUnitValueRepository.findByMetaSystemUnit_Id(metaSystemUnit.getId());

        Map<String, Context> result = new HashMap<>();
        //获取使用习惯字典
        values.forEach((o) -> {
            MetaUnitCategory metaUnitCategory = o.getMetaUnitCategory();
            String forwardUnitName = o.getMetaUnitCategoryValue().getUnitName();
            //使用默认国际单位 不需要转换
            if (!metaUnitCategory.getInternationalUnits().equals(forwardUnitName)) {
                String typeName = metaUnitCategory.getUnitName();
                result.put(typeName, getContext(typeName, forwardUnitName));
            }
        });
        return result;
    }

    private Context getContext(String typeName, String forwardUnitName) {
        return getContext(typeName, null, forwardUnitName);
    }

    public Context getContext(String typeName, String backwardUnitName, String forwardUnitName) {
        Context context = TypeFactory.getConvertFactory(typeName);
        context.setBackwardConvert(backwardUnitName).setForwardConvert(forwardUnitName);
        return context;
    }
}
